package com.txzt.gaea.business.project.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.txzt.gaea.business.project.domain.model.ProjectFundExpenseRequest;
import com.txzt.gaea.business.project.domain.model.ProjectFundExpenseRequestDetail;
import com.txzt.gaea.business.project.domain.model.ProjectFundExpenseRequestDetailVo;
import com.txzt.gaea.business.project.domain.vo.*;
import com.txzt.gaea.business.project.service.IProjectFERService;
import com.txzt.gaea.business.sequence.service.ISequenceService;
import com.txzt.gaea.common.annotation.EntityCommonValue;
import com.txzt.gaea.common.base.service.impl.BaseServiceImpl;
import com.txzt.gaea.common.core.base.context.AdminUserContext;
import com.txzt.gaea.common.enums.*;
import com.txzt.gaea.flow.model.FlowBizStep;
import com.txzt.gaea.flow.service.FlowService;
import com.txzt.gaea.vo.AdminUserVO;
import org.beetl.sql.core.engine.PageQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;


@Service
public class ProjectFERServiceImpl extends BaseServiceImpl<ProjectFundExpenseRequest> implements IProjectFERService {

    @Autowired
    private FlowService flowService;
    @Autowired
    private ISequenceService sequenceService;

    @Override
    public PageQuery<ProjectFERStats> ProjectFERStatsList(PageQuery<ProjectFERStats> pageQuery){
        return sqlManager.pageQuery("projectFundExpenseRequest.queryProjectList", ProjectFERStats.class, pageQuery);
    }

    @Override
    public List<ProjectFERStatsDetail> getProjectFERStatsDetail(ProjectFERStatsDetail projectFERStatsDetail){
        List<ProjectFERStatsDetail> standardList = createStandardList(projectFERStatsDetail);
        List<ProjectFERStatsDetail> list =
                sqlManager.select("projectFundExpenseRequest.queryProjectDetail",ProjectFERStatsDetail.class, projectFERStatsDetail);
        for (ProjectFERStatsDetail ferStatsDetail : standardList) {
            for (ProjectFERStatsDetail statsDetail : list) {
                if (ferStatsDetail.getCostType().equals(statsDetail.getCostType())) {
                    ferStatsDetail.setExpenseTotal(statsDetail.getExpenseTotal());
                    ferStatsDetail.setActualExpense(statsDetail.getActualExpense());
                    if (null == statsDetail.getActualExpense()){
                        ferStatsDetail.setActualExpense(BigDecimal.ZERO);
                        ferStatsDetail.setPercentage("0.00%");
                    }else{
                        BigDecimal divideBigDecimal = statsDetail.getActualExpense().divide(statsDetail.getExpenseTotal(),8, RoundingMode.HALF_UP);
                        ferStatsDetail.setPercentage(divideBigDecimal.multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP) + "%");
                    }
                    break;
                }
            }
        }
        return standardList;
    }

    private List<ProjectFERStatsDetail> createStandardList(ProjectFERStatsDetail projectFERStatsDetail){
        List<ProjectFERStatsDetail> standardList = new ArrayList<>();
        ProjectFERStatsDetail standardDetail = new ProjectFERStatsDetail();
        standardDetail.setProjectId(projectFERStatsDetail.getProjectId());
        standardDetail.setCostType(CostType.DEVICE.getCode());
        standardDetail.setCostTypeName(CostType.DEVICE.getInfo());
        standardList.add(standardDetail);
        standardDetail = new ProjectFERStatsDetail();
        standardDetail.setProjectId(projectFERStatsDetail.getProjectId());
        standardDetail.setCostType(CostType.MATERIAL.getCode());
        standardDetail.setCostTypeName(CostType.MATERIAL.getInfo());
        standardList.add(standardDetail);
        standardDetail = new ProjectFERStatsDetail();
        standardDetail.setProjectId(projectFERStatsDetail.getProjectId());
        standardDetail.setCostType(CostType.COOPERATION.getCode());
        standardDetail.setCostTypeName(CostType.COOPERATION.getInfo());
        standardList.add(standardDetail);
        standardDetail = new ProjectFERStatsDetail();
        standardDetail.setProjectId(projectFERStatsDetail.getProjectId());
        standardDetail.setCostType(CostType.FUEL.getCode());
        standardDetail.setCostTypeName(CostType.FUEL.getInfo());
        standardList.add(standardDetail);
        standardDetail = new ProjectFERStatsDetail();
        standardDetail.setProjectId(projectFERStatsDetail.getProjectId());
        standardDetail.setCostType(CostType.TTI.getCode());
        standardDetail.setCostTypeName(CostType.TTI.getInfo());
        standardList.add(standardDetail);
        standardDetail = new ProjectFERStatsDetail();
        standardDetail.setProjectId(projectFERStatsDetail.getProjectId());
        standardDetail.setCostType(CostType.PDII.getCode());
        standardDetail.setCostTypeName(CostType.PDII.getInfo());
        standardList.add(standardDetail);
        standardDetail = new ProjectFERStatsDetail();
        standardDetail.setProjectId(projectFERStatsDetail.getProjectId());
        standardDetail.setCostType(CostType.LABOR.getCode());
        standardDetail.setCostTypeName(CostType.LABOR.getInfo());
        standardList.add(standardDetail);
        standardDetail = new ProjectFERStatsDetail();
        standardDetail.setProjectId(projectFERStatsDetail.getProjectId());
        standardDetail.setCostType(CostType.EXPERT.getCode());
        standardDetail.setCostTypeName(CostType.EXPERT.getInfo());
        standardList.add(standardDetail);
        standardDetail = new ProjectFERStatsDetail();
        standardDetail.setProjectId(projectFERStatsDetail.getProjectId());
        standardDetail.setCostType(CostType.other.getCode());
        standardDetail.setCostTypeName(CostType.other.getInfo());
        standardList.add(standardDetail);
        standardDetail = new ProjectFERStatsDetail();
        standardDetail.setProjectId(projectFERStatsDetail.getProjectId());
        standardDetail.setCostType(CostType.INDIRECT.getCode());
        standardDetail.setCostTypeName(CostType.INDIRECT.getInfo());
        standardList.add(standardDetail);
        return standardList;
    }

    @Override
    public PageQuery<ProjectFERLedger> ProjectFERLedgerList(PageQuery<ProjectFERLedger> pageQuery){
        return sqlManager.pageQuery("projectFundExpenseRequest.queryLedgerList", ProjectFERLedger.class, pageQuery);
    }

    @Override
    public List<ProjectFERLedgerDetail> getProjectFERLedgerDetail(ProjectFERLedgerDetail projectFERLedgerDetail){
        return sqlManager.select("projectFundExpenseRequest.queryLedgerDetail", ProjectFERLedgerDetail.class, projectFERLedgerDetail);
    }

    /**
     * 查询待审核数量(项目过程经费支出申请)
     * @param projectFund
     * @return
     */
    @Override
    public Long listCheckCount(ProjectFundExpenseRequest projectFund) {
        List<Long> list = sqlManager.select("projectFundExpenseRequest.selectProjectFundCheckCount", Long.class, projectFund);
        return list.get(0);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int savePFER(ProjectFundExpenseRequest pfer) {
        AdminUserVO adminUserVO = AdminUserContext.getUser();
        Calendar calendar = Calendar.getInstance();
        // 获取当前年
        int year = calendar.get(Calendar.YEAR);
        Integer sequence = sequenceService.getSequence("project_fund_expense_request", "fer_no");
        String no = year + "JFSQ" + String.format("%03d", sequence);
        pfer.setFerNo(no);
        pfer.setExpenseTime(new Date());
        pfer.setExpenseBy(adminUserVO.getId());
        int count = sqlManager.insertTemplate(pfer,true);
        if (ProjectFERStatus.CHECK.getCode().equals(pfer.getStatus())){
            //开启流程
            Long flowBizId = flowService.startFlowUpgrade(pfer.getId(), "tb_project_fund_expense_request",
                    "status", ProjectFERStatus.BACK.getCode(), ProjectFERStatus.PASS.getCode(),
                    null, ProjectFERStatus.INIT.getCode(),
                    FlowFlagEnum.PROJECT_EXPENSE_REQUEST.getCode(),pfer.getDeptId());
            ProjectFundExpenseRequest target = new ProjectFundExpenseRequest();
            target.setId(pfer.getId());
            target.setFlowId(flowBizId);
            sqlManager.updateTemplateById(target);
        }
        //明细处理
        saveDetail(pfer);
        sqlManager.updateTemplateById(pfer);
        return count;
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    @EntityCommonValue(operation = "CREATE")
    public Long savePFERForProjectMain(ProjectFundExpenseRequest pfer) {
        AdminUserVO adminUserVO = AdminUserContext.getUser();
        Calendar calendar = Calendar.getInstance();
        // 获取当前年
        int year = calendar.get(Calendar.YEAR);
        Integer sequence = sequenceService.getSequence("project_fund_expense_request", "fer_no");
        String no = year + "JFSQ" + String.format("%03d", sequence);
        pfer.setFerNo(no);
        pfer.setStatus(ProjectFERStatus.CHECK.getCode());
        pfer.setExpenseTime(new Date());
        pfer.setExpenseBy(adminUserVO.getId());
        pfer.setOrgId(pfer.getDeptId());
        sqlManager.insertTemplate(pfer,true);
        if (ProjectFERStatus.CHECK.getCode().equals(pfer.getStatus())){
            //开启流程
            Long flowBizId = flowService.startFlowUpgrade(pfer.getId(), "tb_project_fund_expense_request",
                    "status", ProjectFERStatus.BACK.getCode(), ProjectFERStatus.PASS.getCode(),
                    null, ProjectFERStatus.INIT.getCode(),
                    FlowFlagEnum.PROJECT_EXPENSE_REQUEST.getCode(),pfer.getDeptId());
            ProjectFundExpenseRequest target = new ProjectFundExpenseRequest();
            target.setId(pfer.getId());
            target.setFlowId(flowBizId);
            sqlManager.updateTemplateById(target);
        }
        //明细处理
        saveDetail(pfer);
        sqlManager.updateTemplateById(pfer);
        return pfer.getId();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updatePFEROnlySave(ProjectFundExpenseRequest pfer) {
        if (ProjectFERStatus.BACK.getCode().equals(pfer.getStatus())){
            flowService.nextStepOnlyForBack(pfer.getFlowId());
        }
        //明细处理
        saveDetail(pfer);
        return sqlManager.updateTemplateById(pfer);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updatePFER(ProjectFundExpenseRequest pfer) {
        if (ProjectFERStatus.BACK.getCode().equals(pfer.getStatus())){
            flowService.nextStepOnlyForBack(pfer.getFlowId());
        }else if (ProjectFERStatus.INIT.getCode().equals(pfer.getStatus())) {
            //开启流程
            Long flowBizId = flowService.startFlowUpgrade(pfer.getId(), "tb_project_fund_expense_request",
                    "status", ProjectFERStatus.BACK.getCode(), ProjectFERStatus.PASS.getCode(),
                    null, ProjectFERStatus.INIT.getCode(),
                    FlowFlagEnum.PROJECT_EXPENSE_REQUEST.getCode(),pfer.getDeptId());
            pfer.setFlowId(flowBizId);
        }
        pfer.setStatus(ProjectFERStatus.CHECK.getCode());
        //明细处理
        saveDetail(pfer);
        return sqlManager.updateTemplateById(pfer);
    }

    /**
     * 提交审核数据撤回
     * @param projectFundExpenseRequest
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int revocationPFER(ProjectFundExpenseRequest projectFundExpenseRequest) {
        ProjectFundExpenseRequest info = sqlManager.
                single(ProjectFundExpenseRequest.class,projectFundExpenseRequest.getId());
        //状态必须为  审核中
        if (!ProjectFERStatus.CHECK.getCode().equals(info.getStatus())){
            return 99;
        }
        List<FlowBizStep> stepList = sqlManager.query(FlowBizStep.class)
                .andEq("flow_biz_id",projectFundExpenseRequest.getFlowId())
                .andEq("is_delete", IsDeleteEnum.NOTDELETE.getCode())
                .orderBy("step_no asc")
                .select();
        if (0 == stepList.size()) {
            return 99;
        }else {
            //若当前流程第一步未审核，则可撤回
            if (null == stepList.get(0).getStepStatus()) {
                ProjectFundExpenseRequest target = new ProjectFundExpenseRequest();
                target.setId(info.getId());
                //状态退回至待提交
                target.setStatus(ProjectFERStatus.INIT.getCode());
                return sqlManager.updateTemplateById(target);
            }else {
                return 99;
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteInfo(Long id){
        sqlManager.query(ProjectFundExpenseRequest.class).andEq("id",id).delete();
        sqlManager.query(ProjectFundExpenseRequestDetail.class)
                .andEq("fer_id",id).delete();
    }

    /**
     * 支出填写
     * @param projectFundExpenseRequest
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int expenseInfo(ProjectFundExpenseRequest projectFundExpenseRequest){
        saveDetail(projectFundExpenseRequest);
        return sqlManager.updateTemplateById(ProjectFundExpenseRequest.class,projectFundExpenseRequest);
    }

    @Transactional(rollbackFor = Exception.class)
    void saveDetail(ProjectFundExpenseRequest projectFundExpenseRequest){
        List<String> projectList = new ArrayList<>();
        Calendar calendar = Calendar.getInstance();
        // 获取当前年
        int year = calendar.get(Calendar.YEAR);
        //删除原有数据
        sqlManager.query(ProjectFundExpenseRequestDetail.class)
                .andEq("fer_id",projectFundExpenseRequest.getId()).delete();
        BigDecimal totalExpenseBudget = new BigDecimal(0);
        BigDecimal totalActualExpense = new BigDecimal(0);
        //输入数据
        List<ProjectFundExpenseRequestDetail> ferdList = new ArrayList<>();
        if (ProjectFERFundType.FYZXFHY.getCode().equals(projectFundExpenseRequest.getFundType()) ||
                ProjectFERFundType.XCFTKC.getCode().equals(projectFundExpenseRequest.getFundType())){
            List<ProjectFERMeetingDetail> dlist =
                    JSONObject.parseArray(projectFundExpenseRequest.getProjectDetail(),ProjectFERMeetingDetail.class);
            for (ProjectFERMeetingDetail projectFERMeetingDetail : dlist) {
                ProjectFundExpenseRequestDetail p1 = new ProjectFundExpenseRequestDetail();
                p1.setFerId(projectFundExpenseRequest.getId());
                p1.setProjectId(projectFERMeetingDetail.getId());
                p1.setFundType(projectFundExpenseRequest.getFundType());
                if (null != projectFERMeetingDetail.getMeetingActualExpense()){
                    p1.setActualExpense(projectFERMeetingDetail.getMeetingActualExpense());
                }else{
                    p1.setActualExpense(BigDecimal.ZERO);
                }
                p1.setRequestExpense(projectFERMeetingDetail.getMeetingRequestExpense());
                p1.setYear(year);
                p1.setExpenseFundType(projectFERMeetingDetail.getCostType());
                ferdList.add(p1);
                if (null != projectFERMeetingDetail.getMeetingRequestExpense()) {
                    totalExpenseBudget = totalExpenseBudget.add(projectFERMeetingDetail.getMeetingRequestExpense());
                }
                if (null != projectFERMeetingDetail.getMeetingActualExpense()){
                    totalActualExpense = totalActualExpense.add(projectFERMeetingDetail.getMeetingActualExpense());
                }
                ProjectFundExpenseRequestDetail p2 = new ProjectFundExpenseRequestDetail();
                p2.setFerId(projectFundExpenseRequest.getId());
                p2.setProjectId(projectFERMeetingDetail.getId());
                p2.setFundType(projectFundExpenseRequest.getFundType());
                if (null != projectFERMeetingDetail.getMeetingActualExpense()){
                    p2.setActualExpense(projectFERMeetingDetail.getConsultActualExpense());
                }else{
                    p2.setActualExpense(BigDecimal.ZERO);
                }
                p2.setRequestExpense(projectFERMeetingDetail.getConsultRequestExpense());
                p2.setExpenseFundType(projectFERMeetingDetail.getCostTypeExtra());
                p2.setYear(year);
                ferdList.add(p2);
                if (null != projectFERMeetingDetail.getConsultRequestExpense()){
                    totalExpenseBudget = totalExpenseBudget.add(projectFERMeetingDetail.getConsultRequestExpense());
                }
                if (null != projectFERMeetingDetail.getConsultActualExpense()){
                    totalActualExpense = totalActualExpense.add(projectFERMeetingDetail.getConsultActualExpense());
                }
                projectList.add(projectFERMeetingDetail.getProjectName() + ":" + projectFERMeetingDetail.getLedgerAccountName());
            }
        }else {
            List<ProjectFundExpenseRequestDetailVo> dlist =
                    JSONObject.parseArray(projectFundExpenseRequest.getProjectDetail(),ProjectFundExpenseRequestDetailVo.class);
            for (ProjectFundExpenseRequestDetailVo projectFundExpenseRequestDetailVo : dlist) {
                ProjectFundExpenseRequestDetail projectFundExpenseRequestDetail = new ProjectFundExpenseRequestDetail();
                projectFundExpenseRequestDetail.setProjectId(projectFundExpenseRequestDetailVo.getId());
                projectFundExpenseRequestDetail.setRequestExpense(projectFundExpenseRequestDetailVo.getRequestExpense());
                if (null != projectFundExpenseRequestDetailVo.getActualExpense()){
                    projectFundExpenseRequestDetail.setActualExpense(projectFundExpenseRequestDetailVo.getActualExpense());
                }else{
                    projectFundExpenseRequestDetail.setActualExpense(BigDecimal.ZERO);
                }
                projectFundExpenseRequestDetail.setFerId(projectFundExpenseRequestDetailVo.getId());
                projectFundExpenseRequestDetail.setFundType(projectFundExpenseRequest.getFundType());
                projectFundExpenseRequestDetail.setYear(year);
                projectFundExpenseRequestDetail.setExpenseFundType(changeType(projectFundExpenseRequest.getFundType()));
                ferdList.add(projectFundExpenseRequestDetail);
                if (null != projectFundExpenseRequestDetail.getRequestExpense()){
                    totalExpenseBudget = totalExpenseBudget.add(projectFundExpenseRequestDetail.getRequestExpense());
                }
                if (null != projectFundExpenseRequestDetail.getActualExpense()){
                    totalActualExpense = totalActualExpense.add(projectFundExpenseRequestDetail.getActualExpense());
                }
                projectList.add(projectFundExpenseRequestDetailVo.getProjectName() + ":" + projectFundExpenseRequestDetailVo.getLedgerAccountName());
            }
        }
        projectFundExpenseRequest.setProjectList(String.join(",",projectList));
        projectFundExpenseRequest.setTotalExpenseBudget(totalExpenseBudget);
        projectFundExpenseRequest.setTotalActualExpense(totalActualExpense);
        sqlManager.insertBatch(ProjectFundExpenseRequestDetail.class, ferdList);
    }

    private String changeType(String type){
        if (ProjectFERFundType.SBF.getCode().equals(type)){
            return CostType.DEVICE.getCode();
        }else if (ProjectFERFundType.CLF.getCode().equals(type)){
            return CostType.MATERIAL.getCode();
        }else if (ProjectFERFundType.WBXZF.getCode().equals(type)){
            return CostType.COOPERATION.getCode();
        }else if (ProjectFERFundType.RLDLF.getCode().equals(type)){
            return CostType.FUEL.getCode();
        }else if (ProjectFERFundType.CBWXXXCBZSCQSWF.getCode().equals(type)){
            return CostType.PDII.getCode();
        }else if (ProjectFERFundType.FYZXFHY.getCode().equals(type)
                || ProjectFERFundType.XCFTKC.getCode().equals(type)
                || ProjectFERFundType.GJHZYJLF.getCode().equals(type)
                || ProjectFERFundType.CAILF.getCode().equals(type)){
            return CostType.TTI.getCode();
        }else if (ProjectFERFundType.FYZXFTX.getCode().equals(type)){
            return CostType.EXPERT.getCode();
        }else if (ProjectFERFundType.LWF.getCode().equals(type)){
            return CostType.LABOR.getCode();
        }else if (ProjectFERFundType.JJF.getCode().equals(type)){
            return ExpenseType.INDIRECT.getCode();
        }else if (ProjectFERFundType.QTZC.getCode().equals(type)){
            return CostType.other.getCode();
        }
        return null;
    }
}
